package com.seventh.blecore;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.inuker.bluetooth.library.search.SearchResult;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import static com.inuker.bluetooth.library.Code.BLE_NOT_SUPPORTED;
import static com.inuker.bluetooth.library.Code.BLUETOOTH_DISABLED;
import static com.inuker.bluetooth.library.Code.ILLEGAL_ARGUMENT;
import static com.inuker.bluetooth.library.Code.REQUEST_DENIED;
import static com.inuker.bluetooth.library.Code.REQUEST_FAILED;
import static com.inuker.bluetooth.library.Code.REQUEST_SUCCESS;
import static com.inuker.bluetooth.library.Code.REQUEST_TIMEDOUT;
import static com.inuker.bluetooth.library.Code.SERVICE_UNREADY;

/**
 * Unity调用Android：入参可以是 基础类型 +string +基础类型的数组，返回类型也是这样 Object类型需要构造AndroidJavaObject("com....",params)
 * Android 调用Unity:入参可以是 基础类型+string,不支持数组，数组可以是 AndroidJavaObject包裹一下 然后调用里面的属性和方法(必须是基础类型数组，参照上面)
 *
 * @author chengxin
 * create at 2021/4/20
 * description:工具类
 */
public class Utils {

    public static final String UNITY_PLAYER_NAME = "com.unity3d.player.UnityPlayer";
    /**
     * 是否为Unity平台
     */
    public static final boolean UNITY_PLATFORM;

    static {
        //默认false
        boolean platform = false;
        try {
            Class.forName(UNITY_PLAYER_NAME);
            platform = true;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        UNITY_PLATFORM = platform;
    }

    static final String TAG = "UNITY_BLE";

    private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());

    //缓存Method和class
    @Nullable
    private static Class<?> UnityPlayer;
    @Nullable
    private static Method UnitySendMessage;

    /**
     * 调用Unity的方法
     * 版权声明：本文为CSDN博主「德星」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
     * 原文链接：https://blog.csdn.net/kongxingxing/article/details/81119831
     *
     * @param gameObjectName 调用的GameObject的名称
     * @param functionName   方法名
     * @param args           参数
     * @return 调用是否成功
     */
    public static boolean callUnity(@NonNull String gameObjectName, @NonNull String functionName, @NonNull String args) {
        try {
            if (UnitySendMessage == null) {
                UnityPlayer = Class.forName(UNITY_PLAYER_NAME);
                UnitySendMessage = UnityPlayer.getMethod("UnitySendMessage", String.class, String.class, String.class);
            }
            UnitySendMessage.invoke(UnityPlayer, gameObjectName, functionName, args);
            return true;
        } catch (ClassNotFoundException |
                NoSuchMethodException |
                IllegalAccessException |
                InvocationTargetException ignored) {
            return false;
        }
    }

    /**
     * 获取unity项目的上下文
     *
     * @return _unityActivity
     */
    public static Activity getUnityActivity() {
        //调用Unity的方法
        //通过报名获取java class (固定写法，好坑，不要以为是自已的Android包名)
        //AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        //获取当前的activity （固定写法，不要以为是自己定义的Activity名称。。。）
        //AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        try {
            Class<?> classType = Class.forName(UNITY_PLAYER_NAME);
            return (Activity) classType.getDeclaredField("currentActivity").get(classType);
        } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {
            throw new IllegalStateException("无法获取unity context", e);
        }
    }

    /**
     * @return 判断是否在主线程
     */
    public static boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }

    public static void showToast(@NonNull final Context context, @NonNull final String msg) {
        if (!isMainThread()) {
            postToMainThread(new Runnable() {
                @Override
                public void run() {
                    showToast(context, msg);
                }
            });
            return;
        }
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }

    public static void postToMainThread(@NonNull Runnable runnable) {
        MAIN_HANDLER.post(runnable);
    }

    public static JSONArray convertToJsonArray(@NonNull List<SearchResult> resultList) {
        JSONArray jsonArray = new JSONArray();
        for (SearchResult result : resultList) {
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("name", result.getName());
                jsonObject.put("mac", result.getAddress());
                jsonObject.put("rssi", result.rssi);
                jsonArray.put(jsonObject);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return jsonArray;
    }

    public static String connectCodeToString(int code) {
        switch (code) {
            case REQUEST_SUCCESS:
                return "连接成功";
            case REQUEST_FAILED:
                return "连接失败";
            case ILLEGAL_ARGUMENT:
                return "连接参数错误";
            case BLE_NOT_SUPPORTED:
                return "蓝牙不支持连接";
            case BLUETOOTH_DISABLED:
                return "蓝牙不可用";
            case SERVICE_UNREADY:
                return "服务为准备好";
            case REQUEST_TIMEDOUT:
                return "连接请求超时";
            case REQUEST_DENIED:
                return "连接被拒绝";
            default:
                return "unknown code: " + code;
        }
    }

    /**
     * 简单的打印日志的方法
     */
    public static void d(@Nullable Object obj) {
        String value = String.valueOf(obj);
        try {
            String json = value.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                String message = jsonObject.toString(2);
                Log.d(TAG, message);
                return;
            }
            if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                String message = jsonArray.toString(2);
                Log.d(TAG, message);
                return;
            }
        } catch (JSONException ignored) {
        }
        Log.d(TAG, value);
    }

    /**
     * 字节数组转16进制
     *
     * @param bytes 需要转换的byte数组
     * @return 转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            sb.append("0x");
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
            sb.append(",");
        }
        return sb.toString();
    }
}